# -*- coding: utf-8 -*-
from httplib import *
import hashlib
from xml.dom.minidom import *
import re
import urllib
from PyKDE4.phonon import Phonon
from PyQt4.QtCore import *
from PyQt4.QtNetwork import *
from lastfm import LastFMConnection, LastFMTrack, LastFMError

class LastFMConnectionQt(LastFMConnection, QObject):

	def __init__(self, debug = False):

		QObject.__init__(self)
		LastFMConnection.__init__(self, debug)

		self.connection = QHttp('ws.audioscrobbler.com')
		self.connect(self.connection, SIGNAL('responseHeaderReceived(QHttpResponseHeader)'), self.processHeader)

	# This method is to be called first, when there is no session
	# key yet.

	def requestToken(self):

		url = self.buildUrl({'method':'auth.getToken', 'api_key':self.apiKey})
		#self.ensureConnection()
		self.connect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processToken)
		self.httpGet(url)
		
	def processToken(self, id, error):

		self.disconnect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processToken)
		if error or self.responseHeader.statusCode() != 200:

			self.emit(SIGNAL('tokenFailure(QString)'), 'HTTP GET Failed')
		else:
	
			dom = parseString(self.httpBody())
			try:

				self.token = self.extractXMLValues(dom, 'lfm/token')[0]
			except IndexError:

				self.emit(SIGNAL('tokenFailure(QString)'), 'Could not extract token from response.')
			else:

				link = 'http://www.last.fm/api/auth/?api_key='+self.apiKey+'&token='+self.token
				self.emit(SIGNAL('tokenSuccess(QString)'), link)

	# This method will only work after requestToken() has been sucessfully
	# called, and permission has been granted on the last.fm website.

	def requestSession(self):
	
		url = self.buildUrl({'api_key':self.apiKey, 'method':'auth.getSession', 'token':self.token})		
		#self.ensureConnection()
		self.connect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processSession)
		self.httpGet(url)
		
	def processSession(self, id, error):

		self.disconnect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processSession)
		if error or self.responseHeader.statusCode() != 200:

			self.emit(SIGNAL('sessionFailure(QString)'), 'HTTP GET Failed')
		else:
	
			dom = parseString(self.httpBody())
			try:

				self.sessionKey = self.extractXMLValues(dom, 'lfm/session/key')[0]
			except IndexError:

				self.emit(SIGNAL('sessionFailure(QString)'), 'Could not extract session key from response.')
			else:

				self.emit(SIGNAL('sessionSuccess(QString)'), self.sessionKey)

	# this method can be called if there is a session key available.

	def requestStation(self, station):

		params = {'method':'radio.tune', 'station':station, 'api_key':self.apiKey, 'sk':self.sessionKey}
		self.addApiSignature(params)
		self.connect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processStation)
		self.httpPost(params)

	def processStation(self, id, error):

		self.disconnect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processStation)
		if error or self.responseHeader.statusCode() != 200:

			self.emit(SIGNAL('stationFailure(QString)'), 'HTTP POST Failed')
		else:
	
			self.emit(SIGNAL('stationSuccess()'))

	# this method can be called, after a station was set correctly

	def requestTracks(self):

		url = self.buildUrl({'method':'radio.getPlaylist', 'api_key':self.apiKey, 'sk':self.sessionKey})
		self.connect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processTracks)
		self.httpGet(url)

	def processTracks(self, id, error):

		self.disconnect(self.connection, SIGNAL('requestFinished(int, bool)'), self.processTracks)
		if error or self.responseHeader.statusCode() != 200:

			self.emit(SIGNAL('tracksFailure(QString)'), 'HTTP POST Failed')
		else:
	
			dom = parseString(self.httpBody())
			locations = self.extractXMLValues(dom, 'playlist/trackList/track*/location')
			titles = self.extractXMLValues(dom, 'playlist/trackList/track*/title')
			creators = self.extractXMLValues(dom, 'playlist/trackList/track*/creator')
			images = self.extractXMLValues(dom, 'playlist/trackList/track*/image')
			tracks = list()

			for location, title, creator, image in zip(locations, titles, creators, images):
				
				track = LastFMTrack(location)
				track.title = title
				track.artist = creator
				track.art = image
				tracks.append(track)
			self.emit(SIGNAL('tracksSuccess(PyQt_PyObject)'), tracks)

	# convenience methods

	def buildUrl(self, params):

		self.addApiSignature(params)
		return '/2.0/?'+urllib.urlencode(params)

	# http methods

	def processHeader(self, header):

		self.responseHeader = header
		if self.debug:

			print header.statusCode(), header.reasonPhrase()

	def httpGet(self, url):

		self.buffer = QBuffer()
		self.connection.get(url, self.buffer)

	def httpPost(self, params):

		data = QByteArray(urllib.urlencode(params))
		header = QHttpRequestHeader('POST', '/2.0/')
		header.setContentType('application/x-www-form-urlencoded')
		header.setValue('Host', 'ws.audioscrobbler.com')
		self.buffer = QBuffer()
		self.connection.request(header, urllib.urlencode(params), self.buffer)

	def httpBody(self):

		body = self.buffer.data()
		if self.debug:

			print body
		return body
